home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/graphics_protos.h>
- #include <clib/feelin_protos.h>
-
- #include <libraries/feelin.h>
-
- struct FeelinBase *FeelinBase;
-
- ///OBJ
- // This is the instance data for our custom class.
-
- struct LocalObjectData {
- WORD x,y, sx,sy;
- };
- //+
-
- /// mAskMinMax
- /*
- Area.AskMinMax() will be called before the window is opened. We need to
- tell Feelin the minimum and maximum size of our object.
-
- When you are the first receiving the method the fields _minw() and
- _minh() are set to zero and the fields _maxw() and _maxh() to FV_MAXMAX.
- We can add values to _minw() and _minh() or set _maxw() and _maxh() if
- we need to. Then we pass the method to our superclass.
-
- When the method reaches Area class these values will be adjusted
- according to FA_MinXxx, FA_FixedXxx and FA_FixXxx attributes.
- */
-
- ULONG SAVEDS mAskMinMax(struct FeelinClass *psClass,APTR Obj,ULONG *pnArgs)
- {
- _minw(Obj) += 100; _minh(Obj) += 040;
- _maxw(Obj) = 500; _maxh(Obj) = 300;
-
- return F_SuperDoA(psClass,Obj,FM_AskMinMax,pnArgs);
- }
- //+
- /// mDraw
- /*
- Draw method is called whenever Feelin feels (obviously ;-)) we should
- render our object. This usually happens after layout is finished. Note:
- You may only render within the rectangle _mleft(), _mtop(), _mwidth(),
- _mheight().
- */
- ULONG SAVEDS mDraw(struct FeelinClass *psClass,APTR Obj,struct LocalObjectData *psLOD,struct FS_Draw *psDraw)
- {
- APTR rp;
-
- /*
- Let our superclass draw itself first, Area class would e.g. draw the
- frame and clear the whole region. What it does exactly depends on flags.
- */
-
- F_SuperDoA(psClass,Obj,FM_Draw,(ULONG *)psDraw);
-
- /*
- IF FF_Draw_Object isn't set, we shouldn't draw anything. Feelin just
- wanted to update the frame or something like that.
- */
-
- rp = _rp(Obj);
-
- if (psDraw->Flags & FF_Draw_Update) // called from our input method
- {
- if (psLOD->sx || psLOD->sy)
- {
- _BPen(_pen(Obj,FV_Pen_Shine));
- ScrollRaster(rp,psLOD->sx,psLOD->sy,_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
- _BPen(_pen(Obj,FV_Pen_Dark));
- psLOD->sx = NULL;
- psLOD->sy = NULL;
- }
- else
- {
- _APen(_pen(Obj,FV_Pen_Shadow));
- _Plot(psLOD->x,psLOD->y);
- }
- }
- else if (psDraw->Flags & FF_Draw_Object)
- {
- _APen(_pen(Obj,FV_Pen_Shine));
- _Boxf(_mx(Obj),_my(Obj),_mx2(Obj),_my2(Obj));
- }
-
- return NULL;
- }
- //+
- /// mActive
- /*
- Area class always creates an EventHandler structure in case of some
- inputmodes. As we handle events instead of Area class we can use it as
- we want. It will save us some allocations ;-)
-
- Using F_ModifyHandler() to modify IDCMP flags it's a piece of cake to
- request IDCMP events.
- */
-
- ULONG SAVEDS mActive(struct FeelinClass *psClass,APTR Obj,BOOL bState)
- {
- if (bState)
- {
- F_Do(Obj,FM_ModifyHandler,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS,NULL);
- }
- else
- {
- F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS);
- }
-
- return F_SuperDoA(psClass,Obj,bState ? FM_Active : FM_Inactive,NULL);
- }
- //+
- ///mHandleEvent
- /*
- in mSetup() we said that we want get a message if mousebuttons or keys
- pressed so we have to define the input-handler
-
- Note :
-
- This is really a good example, because it shows how to use critical
- events carefully:
-
- IDCMP_MOUSEMOVE is only needed when left-mousebutton is pressed, so we
- dont request this until we get a SELECTDOWN-message and we reject
- IDCMP_MOUSEMOVE immeditly after we get a SELECTUP-message
- */
-
- ULONG SAVEDS mHandleEvent(APTR Obj, struct LocalObjectData *psLOD, struct FS_HandleEvent *psHE)
- {
- #define _between(a,x,b) ((x) >= (a) && (x) <= (b))
- #define _isinobject(x,y) (_between(_mx(Obj),(x),_mx(Obj) + _mw(Obj) - 1) && _between(_my(Obj),(y),_my(Obj) + _mh(Obj) - 1))
-
- /*
- Note on Arrows handling :
-
- If you don't handle arrows return NIL, this will allow Window object to
- cycle through its chain using arrows instead of tabulations (more
- confortable hu ?), else return your object. Currently, result is only check
- against NIL, but this may change in future, so return your object.
- */
-
- if (psHE->Key != FV_Key_None)
- {
- switch (psHE->Key)
- {
- case FV_Key_Left: psLOD->sx = -1; break;
- case FV_Key_Right: psLOD->sx = 1; break;
- case FV_Key_Up: psLOD->sy = -1; break;
- case FV_Key_Down: psLOD->sy = 1; break;
- default: return NULL;
- }
-
- F_Draw(Obj,FF_Draw_Update);
-
- return ((ULONG)Obj); // Forbid arrow cycling, because *WE* handle key events.
- }
- else if (psHE->Msg->Class == IDCMP_MOUSEBUTTONS)
- {
- if (psHE->Msg->Code == SELECTDOWN)
- {
- if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
- {
- psLOD->x = psHE->Msg->MouseX;
- psLOD->y = psHE->Msg->MouseY;
- F_Draw(Obj,FF_Draw_Update);
- // Only request IDCMP_MOUSEMOVE if we realy need it
- F_Do(Obj,FM_ModifyHandler,IDCMP_MOUSEMOVE,NULL);
- }
- }
- else
- {
- // Reject IDCMP_MOUSEMOVE because lmb is no longer pressed
- F_Do(Obj,FM_ModifyHandler,NULL,IDCMP_MOUSEMOVE);
- }
- }
- else if (psHE->Msg->Class == IDCMP_MOUSEMOVE)
- {
- if (_isinobject(psHE->Msg->MouseX,psHE->Msg->MouseY))
- {
- psLOD->x = psHE->Msg->MouseX;
- psLOD->y = psHE->Msg->MouseY;
- F_Draw(Obj,FF_Draw_Update);
- }
- }
-
- return NULL;
- }
- //+
- ///myDispatcher
- ULONG ASM SAVEDS myDispatcher(REG_A2 struct FeelinClass *psClass,REG_A0 APTR Obj,REG_D0 ULONG nMethod,REG_A1 ULONG *pnArgs)
- {
- struct LocalObjectData *psLOD;
-
- psLOD = INST_DATA(psClass,Obj);
-
- /*
- Here comes the dispatcher for our custom class. Unknown/unused methods are
- passed to the superclass immediately.
- */
-
- switch (nMethod)
- {
- case FM_AskMinMax: return mAskMinMax (psClass,Obj,pnArgs);
- case FM_Draw: return mDraw (psClass,Obj,psLOD,(struct FS_Draw *)pnArgs);
- case FM_HandleEvent: return mHandleEvent (Obj,psLOD,(struct FS_HandleEvent *)pnArgs);
- case FM_Active: return mActive (psClass,Obj,TRUE);
- case FM_Inactive: return mActive (psClass,Obj,FALSE);
- default: return F_SuperDoA (psClass,Obj,nMethod,pnArgs);
- }
- }
- //+
-
- /// Main
- void main()
- {
- APTR c,w,myobj;
- struct FeelinClass *psFCC;
-
- if (FeelinBase = (struct FeelinBase *)OpenLibrary("feelin.library",FV_VERSION))
- {
- /*
- Create the new custom class with a call to F_CreateClass().
-
- This function returns a feelinClass structure. You must use class.id to
- create instance of your custom class. This ID is unique and made by
- F_CreateClass() when ID is NIL.
- */
-
- if (psFCC = F_CreateClass(FA_SuperID, FC_Area,
- FA_DataSize, sizeof (struct LocalObjectData),
- FA_Dispatcher, myDispatcher,
- TAG_DONE))
- {
- c = ClientObject,
- Child, w = WindowObject, FA_Window_Title, "A rather complex custom class",
- Child, VGroup,
- Child, TextObject, FA_FixedHeight,TRUE, DontChain, TextFrame, TextBack, FA_Text, "`c`iPaint `nwith `bmouse`n,\n`iScroll `nwith `bcursor keys`n.", End,
- Child, myobj = F_NewObj(psFCC->ID, TextFrame, TAG_DONE),
- End,
-
- FA_Window_ActiveObject, myobj, // Safe here
- End,
- End;
-
- if (c)
- {
- F_Do(w,FM_Notify,FA_Window_CloseRequest,TRUE, c,2,FM_Client_ReturnID,FV_Client_Quit);
- F_Set(w,FA_Window_Open,TRUE);
-
- F_DoA(c,FM_Client_Run,NULL);
-
- F_DisposeObj(c);
- }
-
- F_RemoveClass(psFCC);
- }
- else
- {
- Printf("Could not create custom class.\n");
- }
-
- CloseLibrary((struct Library *)FeelinBase);
- }
- else
- {
- Printf("Failed to open feelin.library\n");
- }
- }
- //+
-